/****************************************************************************
 * Elisa 1.0                                                                *
 *--------------------------------------------------------------------------*
 * Author: Laurent Granvilliers, Vincent Sorin                              *
 * Copyright (c) 2004 Laboratoire d'Informatique de Nantes Atlantique       *
 *--------------------------------------------------------------------------*
 * Elisa is distributed WITHOUT ANY WARRANTY. Read the associated           *
 * COPYRIGHT file for more details.                                         *
 *--------------------------------------------------------------------------*
 * elisa_reduction_factory.h                                                *
 ****************************************************************************/

/**
 * @file elisa_reduction_factory.h
 * @brief Classes for the passage from the model to the reduction
 */


#ifndef ELISA_REDUCTION_FACTORY_H
#define ELISA_REDUCTION_FACTORY_H

#include "elisa_defs.h"

#include <vector>
#include <set>
#include <map>

#include <boost/shared_ptr.hpp>

NAMESPACE_ELISA

class ModelRep;
// Forward declaration
class Reduction;

typedef boost::shared_ptr<Reduction> ReductionPtr;

/**
 * @ingroup Reduction
 * @class SetReduction
 * @brief Set of reductions
 */

//typedef std::set<ReductionPtr, std::less<ReductionPtr> > SetReduction;
typedef std::set<Reduction *, std::less<Reduction *> > SetReduction;


/**
 * @ingroup Reduction
 * @class VecReduction
 * @brief Vector of reductions
 */

typedef std::vector<ReductionPtr> VecReduction;

/**
 * @ingroup Reduction
 * @class ReductionFactory
 * @brief Generation of reductions from a model
 */
class ReductionFactory
{
public:
	/**
 	 * Default constructor
 	 */
	ReductionFactory ()
	{
	}

	/**
 	 * Destructor
 	 */
	virtual ~ReductionFactory ()
	{
	}

	/**
 	 * Create the reduction functions according to the model mo and put them in the set s
 	 * @param mo the model
 	 * @param s the set of reduction functions
 	 */
	virtual void create(ModelRep *mo, SetReduction & s) = 0;

	/**
 	 * Create a reduction function according to the model mo
 	 * @param mo the model
 	 */
	virtual Reduction *create(ModelRep *mo)
	{
		SetReduction s;
		create(mo, s);
		if (s.size() == 1)
			return *(s.begin());
		else
			// this never happens.
			return 0;
	}
};


/**
 * @ingroup Reduction
 * @class MapReduction
 * @brief map of factoryReduction. The key is the type of the model
 */

typedef std::map<std::string, boost::shared_ptr<ReductionFactory>, ltstr> MapReduction;


/**
 * @ingroup reduction
 * @class ReductionFactoryChooser
 * @brief Class for the management of the map of factory reduction
 */
class ReductionFactoryChooser
{
public:
	/**
 	 * @brief inserts a ReductionFactory into the map
 	 * @param t1 the type of the model
 	 * @param v pointer to the propagation reduction factory
 	 */
	static void insert(std::string t1, ReductionFactory *c)
	{
		if (_mapReduction[t1] != 0) {
			//delete _mapReduction[t1];
			_mapReduction.erase(t1);
		}
		if (c != 0) {
			_mapReduction[t1] = boost::shared_ptr<ReductionFactory>(c);
			//_mapReduction.insert(std::make_pair(t1, boost::shared_ptr<ReductionFactory>(c)));
		}
	}


	/**
 	 * @brief returns a ReductionFactory
 	 * @param t1 type of the constraints model
 	 * @return a pointer to a ReductionFactory
 	 */
	static ReductionFactory *get(std::string t1)
	{
		return _mapReduction[t1].get();
	}

	/**
 	 * @brief empties the map
 	 * @post the map is empty and all Factory have been deleted
 	 */
	static void clear()
	{
		/*
 		   MapReduction::iterator it;
 		   for (it= _mapReduction.begin();it != _mapReduction.end();++it)
 		   {
 		   delete (*it).second;
 		   }
 		 */
		_mapReduction.clear();
	}

private:
	/**
 	 *@var map used to recover a comparator
 	 */
	static MapReduction _mapReduction;
};

END_NAMESPACE_ELISA
#endif // ELISA_REDUCTION_FACTORY
